home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1993 July / InfoMagic USENET CD-ROM July 1993.ISO / sources / unix / volume15 / ru < prev    next >
Encoding:
Internet Message Format  |  1988-06-06  |  10.3 KB

  1. Subject:  v15i043:  A users(1)-style rwho
  2. Newsgroups: comp.sources.unix
  3. Sender: sources
  4. Approved: rsalz@uunet.UU.NET
  5.  
  6. Submitted-by: pkern <pkern@csri.toronto.edu>
  7. Posting-number: Volume 15, Issue 43
  8. Archive-name: ru
  9.  
  10. [  I haven't tried this; we don't run rwho here...  It reads the
  11.    data out of the /usr/spool/rwho files, and generates nicely
  12.    formatted listings of who's logged in where.  -r$ ]
  13.  
  14. #! /bin/sh
  15. # This is a shell archive, meaning:
  16. # 1. Remove everything above the #! /bin/sh line.
  17. # 2. Save the resulting text in a file.
  18. # 3. Execute the file with /bin/sh (not csh) to create the files:
  19. #    makefile ru.1 ru.c
  20. export PATH; PATH=/bin:$PATH
  21. echo shar: extracting "'makefile'" '(139 characters)'
  22. if test -f 'makefile'
  23. then
  24.     echo shar: will not over-write existing file "'makefile'"
  25. else
  26. cat << \SHAR_EOF > 'makefile'
  27. #
  28. CFLAGS=    -O -s
  29.  
  30. ru:    ru.o
  31.     $(CC) $(CFLAGS) $*.o -o $@
  32.  
  33. man:    ru.1
  34.     nroff -man ru.1 > ru.man
  35.     more -s ru.man
  36.  
  37. clean:
  38.     -rm -f *.o a.out *.man
  39. SHAR_EOF
  40. fi # end of overwriting check
  41. echo shar: extracting "'ru.1'" '(1306 characters)'
  42. if test -f 'ru.1'
  43. then
  44.     echo shar: will not over-write existing file "'ru.1'"
  45. else
  46. cat << \SHAR_EOF > 'ru.1'
  47. .TH RU l local
  48. .UC
  49. .SH NAME
  50. ru, rusers \- compact lists of users on all "visible" systems
  51. .SH SYNOPSIS
  52. .B "/usr/local/ru [-acdms] [-D domain] [-h host ...]"
  53. .br
  54. .B "/usr/local/rusers [-acdms] [-D domain] [-h host ...]"
  55. .SH DESCRIPTION
  56. .I Ru
  57. lists the login names of the users currently on all visible systems.
  58. .SH Options
  59. .IP -a
  60. list all users, regardless of their login idle time (\fIrwho(1)\fP-inspired).
  61. .IP -c
  62. show a count for multiply-logged users.
  63. .IP -d
  64. group hosts within their domains (forces -s option).
  65. .IP -m
  66. show multiple logins (overrides -c option).
  67. .IP -s
  68. list users host-by-host instead of domain-by-domain.
  69. .IP "-D domain"
  70. list only users logged on hosts in the given domain.
  71. .IP "-h host ..."
  72. list only users logged on to the specified hosts.
  73. .PP
  74. Any system for which data can be found in the
  75. .I rwhod(8c)
  76. spooling directory is considered to be a "visible system".
  77. .SH FILES
  78. /usr/spool/rwho/whod.*
  79. .SH SEE ALSO
  80. users(1), rwho(1C), rwhod(8C)
  81. .SH HISTORY
  82. Originally created by splicing pieces of
  83. .I rwho(1)
  84. source into
  85. .I users(1)
  86. source.
  87. Rewritten to try to clean up the hacked code
  88. and to try to make it easier to add (or delete) options.
  89. .SH BUGS
  90. With the -h option,
  91. .I ru
  92. doesn't care if a host's spool file hasn't
  93. been updated within the last 5 minutes.
  94. .SH CONTACT
  95. pkern@utcsri.uucp
  96. SHAR_EOF
  97. fi # end of overwriting check
  98. echo shar: extracting "'ru.c'" '(7817 characters)'
  99. if test -f 'ru.c'
  100. then
  101.     echo shar: will not over-write existing file "'ru.c'"
  102. else
  103. cat << \SHAR_EOF > 'ru.c'
  104. /*
  105.  * ru - remote users(1)        (version 2)
  106.  *    list users on all "visible" hosts.
  107.  *    usage: ru [-acdms] [-D domain] [-h host ...]
  108.  *
  109.  * P. Kern (pkern@utcsri)
  110.  */
  111.  
  112. #include <stdio.h>
  113. #include <sys/types.h>
  114. #include <sys/stat.h>
  115. #include <sys/dir.h>
  116. #include <sys/file.h>
  117. #include <netdb.h>
  118.  
  119. #define MINSTR    8        /* minimum string length */
  120. #define HNSZ    32        /* hostname length */
  121. #define RWFSZ    HNSZ+5        /* spool-file name length */
  122. #define MRGN    12        /* 12 space "tab" */
  123. #define HOUR    3600        /* seconds in an hour */
  124. #define RWPERIOD    300    /* 5 minute rwho refresh period */
  125. #define MAXPORTS    160    /* max tty ports per host */
  126.  
  127. struct rw_utmp {
  128.     char tty[MINSTR];    /* user's tty */
  129.     char name[MINSTR];    /* user's login */
  130.     long time;        /* login time */
  131.     long idle;        /* idle time */
  132. } rut;
  133.  
  134. struct rw_hdr {
  135.     char pad[4];        /* ignore first 4 bytes */
  136.     int sent, rcvd;        /* time sent,  time rec'vd */
  137.     char host[HNSZ];    /* host's name */
  138.     int loadav[3];        /* load averages */
  139.     int boot;        /* boot date */
  140. } hdr;
  141.  
  142. int rutsize, hdrsize;
  143. #define RWHODIR "/usr/spool/rwho"
  144.  
  145. long now;        /* it won't be ... (long now :-) */
  146. int n, fd;
  147. struct stat st;
  148. char *hnbuf, *hp;    /* hostname buffer & extra pointer */
  149. char *rubuf, *ep;    /* utmp data buffer & end pointer */
  150. char *program, *domain;
  151. int aflag=1;    /* only show users with <1 HR idle time */
  152. int sflag=1;    /* show output by domains (not by hosts) */
  153. int mflag=1;    /* ignore multiple logins */
  154. int cflag=0;    /* (if mflag) don't show login counts */
  155. int dflag=1;    /* sort hostnames within domains */
  156. int Dflag=0;    /* show users in a given domain */
  157. int hflag=0;    /* show users on a given host */
  158. int errflag=0;
  159.  
  160. extern char *rindex(), *malloc();
  161.  
  162. main(argc, argv)
  163. int argc;
  164. char *argv[];
  165. {
  166.     DIR *dirp;
  167.     struct direct *dp;
  168.     int rwfcmp(), rutcmp(), drwcmp();    /* qsort() routines */
  169.     extern int optind;    /* see getopt(3C) */
  170.     extern char *optarg;    /* see getopt(3C) */
  171.  
  172.     program = argv[0];
  173.     now = time(0);
  174.     rutsize = sizeof(rut);
  175.     hdrsize = sizeof(hdr);
  176.  
  177.     while ((n = getopt(argc, argv, "acdhmsD:")) != EOF)
  178.         switch(n) {
  179.         case 'a': aflag=0; break;    /* same as rwho(1) */
  180.         case 'c': cflag=1; break;    /* show login count */
  181.         case 'd': dflag=0; break;    /* domain-wise sort */
  182.         case 'm': mflag=0; break;    /* drop multi-logins */
  183.         case 's': sflag=0; break;    /* domain-only lists */
  184.         case 'D': Dflag++; domain = optarg; break;
  185.         case 'h': hflag++; break;
  186.         default: errflag++;
  187.         }
  188.     if (errflag) {
  189.         fprintf(stderr,"Usage: %s [-acdms] [-D domain] [-h host ...]\n", program);
  190.         exit(1);
  191.     }
  192.  
  193.     if (!dflag) sflag=0;
  194.     if (!mflag) cflag=0;    /* not really needed (see burp()) */
  195.  
  196.     if (chdir(RWHODIR) < 0) {    /* cd RWHODIR */
  197.         perror(RWHODIR);
  198.         exit(1);
  199.     }
  200.  
  201.     if (hflag) {
  202.         sflag=0;
  203.         for ( ;optind < argc; optind++)
  204.             dohost(argv[optind]);
  205.         exit(0);
  206.     }
  207.  
  208.     /*
  209.      * read "." directory (assuming chdir() worked), 
  210.      * and get all files with the "whod." prefix.
  211.      * if Dflag, only get files ending with "domain".
  212.      */
  213.     if ((dirp = opendir(".")) == NULL
  214.         || stat(".", &st) < 0) { 
  215.         perror(RWHODIR);
  216.         exit(1);
  217.     }
  218.     dp = readdir(dirp);    /* get "." */
  219.     n = (st.st_size/(DIRSIZ(dp)+8))*RWFSZ;
  220.     hnbuf = malloc((unsigned)n);
  221.     n = 0; ep = hnbuf;
  222.     while (dp = readdir(dirp)) {
  223.         strncpy(ep, dp->d_name, dp->d_namlen);
  224.         *(ep+dp->d_namlen) = '\0';
  225.         if (strncmp(ep, "whod.", 5) == 0 &&
  226.            (!Dflag || strcmp(rindex(ep,'.')+1,domain) == 0)) {
  227.             ep += RWFSZ;
  228.             n++;
  229.         }
  230.     }
  231.     /* ep should now point to the end of the host name buffer */
  232.     closedir(dirp);
  233.  
  234.     if (dflag)    /* sort host names within domains */
  235.         qsort(hnbuf, n, RWFSZ, drwcmp);
  236.     else        /* sort full host name */
  237.         qsort(hnbuf, n, RWFSZ, rwfcmp);
  238.  
  239.     if (sflag) {    /* process by domains only */
  240.         dodomains();
  241.         exit(0);
  242.     }
  243.  
  244.     /*
  245.      * process each "whod." file in hnbuf list.
  246.      * - get <filesize> bytes of mem
  247.      * - gobble rutmp data from file
  248.      * - sort names alphabetically
  249.      * - print names (burp)
  250.      * - free up mem
  251.      */
  252.     hp = hnbuf;
  253.     while (hp < ep) {
  254.         if ((fd = open(hp, O_RDONLY)) < 0
  255.             || fstat(fd, &st) < 0) {
  256.             perror(hp);
  257.             exit(1);
  258.         }
  259.         if (n = st.st_size-hdrsize) {
  260.             if ((rubuf = malloc((unsigned)n)) == 0) {
  261.                 perror(program);
  262.                 exit(1);
  263.             }
  264.             n = read(fd, (char *)&hdr, hdrsize);
  265.             if (now-hdr.rcvd <= RWPERIOD &&
  266.                (n = ldrut(fd,rubuf,st.st_size-hdrsize))>0 ){
  267.                 qsort(rubuf, n/rutsize, rutsize, rutcmp);
  268.                 burp(hp, rubuf, n);
  269.             }
  270.         }
  271.         free(rubuf);
  272.         close(fd);
  273.         hp += RWFSZ;
  274.     }
  275. }
  276.  
  277. /*
  278.  * compare rwho spool-file names
  279.  */
  280. rwfcmp(p, q)
  281. register char *p, *q;
  282. {
  283.     return(strncmp(p, q, RWFSZ));
  284. }
  285.  
  286. /*
  287.  * compare utmp name entries
  288.  */
  289. rutcmp(p, q)
  290. register struct rw_utmp *p, *q;
  291. {
  292.     return(strncmp(p->name, q->name, MINSTR));
  293.  
  294. /*
  295.  * compare sub-domain names
  296.  */
  297. drwcmp(p, q)
  298. register char *p, *q;
  299. {
  300.     int x;
  301.     char *s, *t;
  302.  
  303.     s = rindex(p, '.');
  304.     t = rindex(q, '.');
  305.     if (s) s++; else s = p;
  306.     if (t) t++; else t = q;
  307.     if(x = strncmp(s, t, RWFSZ))
  308.         return(x);
  309.     return(strncmp(p, q, RWFSZ));
  310. }
  311.  
  312. /*
  313.  * print "host:       user1 user2 ... "
  314.  */
  315. burp(s, r, n)
  316. register char *s, *r;
  317. int n;
  318. {    
  319.     register int l;
  320.     register char *xp;
  321.  
  322.     if (!sflag)
  323.         s += 5;        /* skip "whod." prefix */
  324.     if ((l = strlen(s)) > MRGN) {
  325.         s[MRGN]= '\0';
  326.         l = MRGN;
  327.     }
  328.     if (sflag) l += 5;
  329.     printf("%.*s:%*s", MRGN, s, MRGN+1-l, " ");
  330.  
  331.     if (mflag) {
  332.         for(l=0, xp="", s=r+MINSTR; s < (r+n); s += rutsize)
  333.             if (strncmp(s, xp, MINSTR)) {
  334.                 printf( (l)?" %.*s/%d":" %.*s",
  335.                     MINSTR, s, l+1);
  336.                 xp = s; l = 0;
  337.             }
  338.             else
  339.                 l += cflag;
  340.         printf("\n");
  341.         return;
  342.     }
  343.  
  344.     for (s = r+MINSTR; s < (r+n); s += rutsize)
  345.         printf(" %.*s", MINSTR, s);
  346.     printf("\n");
  347. }
  348.  
  349. /*
  350.  * show users on a specific host
  351.  */
  352. dohost(host)
  353. char *host;
  354. {
  355.     struct hostent *h, *gethostbyname();
  356.  
  357.     /*
  358.      * try to get host's proper name
  359.      * and try to find the proper spool file
  360.      */
  361.     if((h = gethostbyname(host)) == NULL) {
  362.         perror(host);
  363.         return(1);
  364.     }
  365.     hp = malloc(strlen(h->h_name)+6);
  366.     sprintf(hp, "whod.%s", h->h_name);
  367.     if ((fd = open(hp, O_RDONLY)) < 0) {
  368.         char **s;
  369.         /*
  370.          * can't find file related to h_name
  371.          * try the aliases instead.
  372.          */
  373.         s = h->h_aliases;
  374.         while(*s) {
  375.             free(hp);
  376.             hp = malloc(strlen(*s)+6);
  377.             sprintf(hp, "whod.%s", *s);
  378.             if ((fd = open(hp, O_RDONLY)) > 0)
  379.                 break;
  380.             s++;
  381.         }
  382.         if (*s == NULL) {
  383.             fprintf(stderr,  "%s: no data\n",  host);
  384.             return(1);
  385.         }
  386.     }
  387.     if (fstat(fd, &st) < 0) {
  388.         perror(hp);
  389.         return(1);
  390.     }
  391.     n = st.st_size - hdrsize;
  392.     if ((rubuf = malloc((unsigned)n)) == 0) {
  393.         perror(program);
  394.         exit(1);
  395.     }
  396.     n = read(fd, (char *)&hdr, hdrsize);
  397.     n = ldrut(fd,rubuf,st.st_size-hdrsize);
  398.     qsort(rubuf, n/rutsize, rutsize, rutcmp);
  399.     if (now-hdr.rcvd > RWPERIOD)
  400.         strcat(hp, "*");
  401.     burp(hp, rubuf, n);
  402. }
  403.  
  404. /*
  405.  * show users by domain
  406.  */
  407. dodomains()
  408. {
  409.     int z;
  410.     register int i;
  411.     char *p0, *p1, *fnp, *rbp;
  412.  
  413.     fnp = hp = hnbuf;
  414.  
  415.     if ((rubuf = malloc(n * MAXPORTS * rutsize)) == NULL) {
  416.         perror(program);
  417.         exit(1);
  418.     }
  419.  
  420.     p0 = rindex(fnp, '.') + 1;
  421.     if ((int)p0 == 1) p0 = fnp;
  422.  
  423.     while (fnp < ep) {
  424.         rbp = rubuf;
  425.         for (p1=p0, n=i=0; fnp < ep && !strcmp(p1, p0); i++) {
  426.             if ((fd = open(fnp, O_RDONLY)) < 0
  427.                 || fstat(fd, &st) < 0) {
  428.                 perror(fnp);
  429.                 exit(1);
  430.             }
  431.             read(fd, (char *)&hdr, hdrsize);
  432.             if (now-hdr.rcvd <= RWPERIOD &&
  433.                (z = ldrut(fd,rbp,st.st_size-hdrsize))>0 ) {
  434.                 n += z;
  435.                 rbp += z;
  436.             }
  437.             close(fd);
  438.             fnp += RWFSZ;
  439.             p1 = p0;
  440.             p0 = rindex(fnp, '.') + 1;
  441.             if ((int)p0 == 1) p0 = fnp;
  442.         }
  443.         if (!n) continue;
  444.         *rbp = '\0';
  445.         qsort(rubuf, n/rutsize, rutsize, rutcmp);
  446.         burp(p1, rubuf, n);
  447.     }
  448.     free(rubuf);
  449. }
  450.  
  451. /*
  452.  * load rutmp data into buffer.
  453.  */
  454. ldrut(fd, p, n)
  455. int fd, n;
  456. char *p;
  457. {
  458.     register int m1, m2, nr;
  459.     register char *s;
  460.  
  461.     if (!aflag) return(read(fd, p, n));
  462.  
  463.     s = p;
  464.     m1 = m2 = 0;
  465.  
  466.     while (m2 < n && (nr = read(fd, s, rutsize)) > 0) {
  467.         m2 += nr;
  468.         if (((struct rw_utmp *)s)->idle > HOUR)
  469.             /* ignore entries with >1 hr idle time */
  470.             continue;
  471.         m1 += nr;
  472.         s += nr;
  473.     }
  474.     return(m1);
  475. }
  476. SHAR_EOF
  477. fi # end of overwriting check
  478. #    End of shell archive
  479. exit 0
  480.  
  481.